package com.cloudinnov.task;

import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.cloudinnov.logic.CapacityStatLogic;
import com.cloudinnov.logic.EquipmentPointLogic;
import com.cloudinnov.logic.ProductionLinesLogic;
import com.cloudinnov.logic.ProductionSchedulesLogic;
import com.cloudinnov.model.CapacityStat;
import com.cloudinnov.model.EquipmentPoints;
import com.cloudinnov.model.ProductionLines;
import com.cloudinnov.model.ProductionSchedule;
import com.cloudinnov.utils.CommonUtils;
import com.cloudinnov.utils.PropertiesUtils;
import com.cloudinnov.websocket.ProductivityWebsocket;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
 * @author chengning
 * @date 2016年8月4日上午12:22:20
 * @email 
 * @remark 产能计算。从redis中获取产量数据点。进行计算（累加），将计算结果存入mysql中产能统计表。
 * @version 
 */
public class ProductionEnergyQuartzJob {

	private static final Logger logger = LoggerFactory.getLogger(ProductionEnergyQuartzJob.class);
	
	DecimalFormat df = new DecimalFormat("######0.00");
	
	private SimpleDateFormat sdf = new SimpleDateFormat(":yyyyMMdd");

	private static final String ENERGY_REDIS_SPILT = "_";

	private static final String POINT_NAME = "point:";
	private static final String HISTORY_SPLITTER_LEVEL1 = ",";
	private static final String HISTORY_SPLITTER_LEVEL2 = ":";
	
	private static final String CAPACITY_REDISKEY ="capacitystat:";
	
	private static final String CAPACITYCOUNT_REDISKEY ="capacitystatcount:";
	

	@Autowired
	private EquipmentPointLogic equipmentPointLogic;

	@Autowired
	private ProductionLinesLogic productionLinesLogic;
	
	@Autowired
	private ProductionSchedulesLogic productionSchedulesLogic;
	
	@Autowired
	private CapacityStatLogic capacityStatLogic;

	@Autowired
	private JedisPool redisPool;

	/** 产能推送服务
	* publish 
	* @Description: TODO(这里用一句话描述这个方法的作用) 
	* @param     参数
	* @return void    返回类型 
	*/
	@SuppressWarnings("static-access")
	protected void publish() {
		//模拟开机
		Calendar cal = Calendar.getInstance();
		
		
		Jedis redis = null;
		try {
			redis = redisPool.getResource();
			Map<String, Object> map = new HashMap<String, Object>();
			ObjectMapper mapper = new ObjectMapper();
			mapper.setSerializationInclusion(Include.NON_NULL);
			List<ProductionLines> result = null ;
			redis.select(Integer.parseInt(PropertiesUtils.findPropertiesKey("redis.db.catastat")));
			Iterator<Map.Entry<String, ProductivityWebsocket>> entries = ProductivityWebsocket.webSocketMap.entrySet()
					.iterator();
			while (entries.hasNext()) {
				Map.Entry<String, ProductivityWebsocket> entry = entries.next();
				List<ProductionLines> productionLines = productionLinesLogic.selectProLineInfoByCode(
						entry.getKey().split(ENERGY_REDIS_SPILT)[0], entry.getKey().split(ENERGY_REDIS_SPILT)[1]);
				for (int i = 0;i<productionLines.size(); i++) {
					String value = redis.lindex(CAPACITY_REDISKEY+productionLines.get(i).getCode(), 0);
					if(value!=null){
						cal.set(Calendar.DATE, cal.get(cal.DATE)-1);
						cal.set(Calendar.HOUR_OF_DAY, 8);
						cal.set(Calendar.MINUTE, 0);
						cal.set(Calendar.SECOND, 0);
						String runTime = String.valueOf((System.currentTimeMillis()-cal.getTimeInMillis())/3600000);
						result = new ArrayList<ProductionLines>();
						productionLines.get(i).setStartTime(String.valueOf(cal.getTimeInMillis()));
						productionLines.get(i).setRunTime(runTime);
						productionLines.get(i).setDayProduction(value.split(HISTORY_SPLITTER_LEVEL1)[1]);
						productionLines.get(i).setValue(Double.parseDouble(value.split(HISTORY_SPLITTER_LEVEL1)[1]));
						productionLines.get(i).setTime(value.split(HISTORY_SPLITTER_LEVEL1)[0]+"000");
						result.add(productionLines.get(i));
					}	
				}			
				if(result!=null&&result.size()>0){
					map.put("list", result);
					entry.getValue().sendMessage(mapper.writeValueAsString(map));
				}	
			}
		} catch (JsonProcessingException e) {
			logger.error("产能推送服务异常 \r{}", e);
		} catch (IOException e) {
			logger.error("产能推送服务异常 \r{}", e);
		} finally {
			redisPool.returnResource(redis);
		}
	}

	/**
	 * 产能计算 productionEnergyCount
	 * 
	 * @Description: TODO(这里用一句话描述这个方法的作用)
	 * @param @throws
	 *            ParseException 参数
	 * @return void 返回类型
	 */
	protected void productionEnergyCount() {
		Jedis redis = null;
		try {
			redis = redisPool.getResource();	
			StringBuilder sb = null;
			// 获取所有生产线上的产能点位
			List<EquipmentPoints> equipmentPoints = equipmentPointLogic.selectProductivityPoint();
			for (EquipmentPoints point : equipmentPoints) {
				redis.select(0);
				sb = new StringBuilder();
				sb.append(POINT_NAME + point.getCode()
						+ CommonUtils.timeStamp2Date(String.valueOf(System.currentTimeMillis() / 1000), ":YYYYMMdd")
						+ "*");
				Set<String> keys = redis.keys(sb.toString());

				// 判断产能点位是否已经参与过计算
				redis.select(Integer.parseInt(PropertiesUtils.findPropertiesKey("redis.db.catastat")));
				String isCan = redis.lindex(CAPACITY_REDISKEY+point.getEquipmentCode(), 0);
				if (isCan != null) {				
					for (String key : keys) {
						redis.select(0);
						// 如果已经统计的时间小于或等于获取到的key的时间则要进行重新对比计算
						if (redis.lindex(key, redis.llen(key)-1) != null
								&& Long.parseLong(isCan.split(HISTORY_SPLITTER_LEVEL1)[0]) <= Long.parseLong(
										redis.lindex(key, redis.llen(key)-1).split(HISTORY_SPLITTER_LEVEL1)[0])) {
							List<String> values = redis.lrange(key, 0, -1);
							redis.select(Integer.parseInt(PropertiesUtils.findPropertiesKey("redis.db.catastat")));
							String time = null;
							// 获得上次的产能
							double energyValue = Double.parseDouble(isCan.split(HISTORY_SPLITTER_LEVEL1)[1]);
							boolean isCheck = false;
							for (String value : values) {
								time = value.split(HISTORY_SPLITTER_LEVEL1)[0];						
								if (Long.parseLong(time) >= Long.parseLong(isCan.split(HISTORY_SPLITTER_LEVEL1)[0])) {
									isCheck = true;
									energyValue += Double.parseDouble(value.split(HISTORY_SPLITTER_LEVEL1)[1]);															
								}
							}					
							if(isCheck){
								// 把此次的size和上次的进行累加放入最新的产能map
								// 最后统计的值和时间放入产能库
								redis.lpush(CAPACITY_REDISKEY+point.getEquipmentCode(),
										time + HISTORY_SPLITTER_LEVEL1 + String.valueOf(df.format(energyValue)));
								redis.ltrim(CAPACITY_REDISKEY+point.getEquipmentCode(), 0, 1000);
								redis.lpush(CAPACITYCOUNT_REDISKEY+point.getEquipmentCode()+sdf.format(new Date()),
										time + HISTORY_SPLITTER_LEVEL1 + String.valueOf(df.format(energyValue)));
							}
							
						}
					}
					// 表示没有进行过统计
				} else {
					// 获取当日产能点位的redis值
					for (String key : keys) {
						redis.select(0);
						// 依次循环当日所有产量的值
						List<String> values = redis.lrange(key, 0, -1);
						// 放入产能统计redis库
						redis.select(Integer.parseInt(PropertiesUtils.findPropertiesKey("redis.db.catastat")));
						String time = null;
						double energyValue = 0;
						boolean isCheak = false;
						for (String value : values) {
							isCheak = true;
							time = value.split(HISTORY_SPLITTER_LEVEL1)[0];
							energyValue += Double.parseDouble(value.split(HISTORY_SPLITTER_LEVEL1)[1]);					
						}
						if(isCheak){
							redis.lpush(CAPACITY_REDISKEY+point.getEquipmentCode(),
									time + HISTORY_SPLITTER_LEVEL1 + String.valueOf(df.format(energyValue)));
							redis.ltrim(CAPACITY_REDISKEY+point.getEquipmentCode(), 0, 1000);
							redis.lpush(CAPACITYCOUNT_REDISKEY+point.getEquipmentCode()+sdf.format(new Date()),
									time + HISTORY_SPLITTER_LEVEL1 + String.valueOf(df.format(energyValue)));
						}
						
					}
				}
			}
		} catch (Exception e) {
			logger.error("产能计算服务异常 \r{}", e);
		} finally {
			redisPool.returnResource(redis);
		}
	}
	
	/** 产能统计任务
	* capacityStatJob 
	* @Description: 每1个小时执行一次
	* @param     参数
	* @return void    返回类型 
	*/
	protected void capacityStatJob() {
		Jedis redis = null;
		try {
			redis = redisPool.getResource();
			redis.select(Integer.parseInt(PropertiesUtils.findPropertiesKey("redis.db.catastat")));
			Set<String> keys = redis.keys(CAPACITYCOUNT_REDISKEY+"*");
			ProductionSchedule productionSchedule;
			for(String key : keys){
				productionSchedule = new ProductionSchedule();
				productionSchedule.setProductionLineCode(key.split(HISTORY_SPLITTER_LEVEL2)[1]);
				//查询生产调度表来获取
				List<ProductionSchedule> list = productionSchedulesLogic.selectListStatByCondition(productionSchedule);
				for(ProductionSchedule productSchedule:list){
					if(!redis.sismember(productSchedule.getCustomerCode()+HISTORY_SPLITTER_LEVEL2+productSchedule.getProductionLineCode(), key)){
						CapacityStat capacityStat = new CapacityStat();
						capacityStat.setProductionLineCode(productSchedule.getProductionLineCode());
						capacityStat.setCustomerCode(productSchedule.getCustomerCode());
						capacityStat.setMaterialCode(productSchedule.getMaterialCode());
						capacityStat.setProductCode(productSchedule.getProductCode());		
						String[] value = redis.lindex(key, 0).split(HISTORY_SPLITTER_LEVEL1);
						capacityStat.setProductionTime(value[0]+"000");
						capacityStat.setYield(value[1]);
						capacityStat.setMaterialCost(Float.parseFloat(productSchedule.getMaterialCost()));
						capacityStat.setSalePrice(productSchedule.getSalePrice());				
						capacityStat.setProfit(String.valueOf(Float.parseFloat(productSchedule.getSalePrice())-Float.parseFloat(productSchedule.getMaterialCost())));
						capacityStatLogic.save(capacityStat);
						redis.sadd(productSchedule.getCustomerCode()+HISTORY_SPLITTER_LEVEL2+productSchedule.getProductionLineCode(), key);
					}					
				}
			}
		} catch(Exception e){
			logger.error(" 产能统计任务异常 \r{}", e);
		}finally {
			redisPool.returnResource(redis);
		}

	}

}
